//-----------------------------------------------------------------------
// <copyright file="Request.cs" company="Robert MacLean">
//     This file is released under the LGPL. For more information see 
//     http://gallery2.codeplex.com.
//     Originally created by Robert MacLean http://www.sadev.co.za
// </copyright>
//-----------------------------------------------------------------------

namespace SADev.Gallery2.Protocol
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.IO;
    using System.Net;
    using System.Linq;

    /// <summary>
    /// This wraps the G2Request functionality
    /// </summary>
    internal class G2Request
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="G2Request"/> class.
        /// </summary>
        public G2Request()
        {
            _protocolVersion = "2.11";
            _cookies = new CookieContainer();
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="G2Request"/> class.
        /// </summary>
        public G2Request(string protocolVersion)
        {
            _protocolVersion = protocolVersion;
            _cookies = new CookieContainer();
        }

        /// <summary>
        /// Gets or sets the host.
        /// </summary>
        /// <value>The host.</value>
        public string Host { get; set; }

        /// <summary>
        /// The protocol version to use
        /// </summary>
        private string _protocolVersion;

        /// <summary>
        /// Stores the cookies.
        /// </summary>
        private CookieContainer _cookies;

        /// <summary>
        /// Executes the specified command.
        /// </summary>
        /// <param name="command">The command.</param>
        /// <param name="values">The values.</param>
        /// <returns></returns>
        public Collection<string> Execute(Commands command, Dictionary<string, string> values)
        {
            return this.Execute(command, values, string.Empty);
        }

        /// <summary>
        /// Executes the specified command.
        /// </summary>
        /// <param name="command">The command.</param>
        /// <param name="values">The values.</param>
        /// <param name="authToken">The auth token.</param>
        /// <returns>
        /// A list of strings, which are the results from G2
        /// </returns>
        public Collection<string> Execute(Commands command, Dictionary<string, string> values, string authToken)
        {
            string url = this.Host + Common.Url;
            if (!string.IsNullOrEmpty(authToken))
            {
                url += "&g2_authToken=" + authToken;
            }

            Dictionary<string, string> commands = new Dictionary<string, string>();

            commands.Add("protocol_version", _protocolVersion);

            switch (command)
            {
                case Commands.Login:
                    {
                        commands.Add("cmd", "login");
                        commands.Add("uname", values["Username"]);
                        commands.Add("password", values["Password"]);
                        break;
                    }

                case Commands.NoOp:
                    {
                        commands.Add("cmd", "no-op");
                        break;
                    }

                case Commands.FetchAlbums:
                    {
                        commands.Add("cmd", "fetch-albums");
                        if (values["Exclude Album Permissions"] == "yes")
                        {
                            commands.Add("no_perms", values["Exclude Album Permissions"]);
                        }
                        break;
                    }

                case Commands.FetchImages:
                    {
                        commands.Add("cmd", "fetch-album-images");
                        commands.Add("set_albumName", values["Album Name"]);
                        commands.Add("albums_too", values["Include Albums"]);
                        commands.Add("random", values["Random"]);
                        if (values.ContainsKey("Limit"))
                        {
                            commands.Add("limit", values["Limit"]);
                        }

                        commands.Add("extrafields", values["Extra Fields"]);
                        commands.Add("all_sizes", values["All Sizes"]);
                        break;
                    }

                case Commands.FetchAlbumsPrune:
                    {
                        commands.Add("cmd", "fetch-albums-prune");
                        if (values["Exclude Album Permissions"] == "yes")
                        {
                            commands.Add("no_perms", values["Exclude Album Permissions"]);
                        }
                        break;
                    }

                case Commands.AlbumProperties:
                    {
                        commands.Add("cmd", "album-properties");
                        commands.Add("set_albumName", values["Album Name"]);
                        break;
                    }

                case Commands.NewAlbum:
                    {
                        commands.Add("cmd", "new-album");
                        commands.Add("newAlbumName", values["Album Name"]);
                        commands.Add("set_albumName", values["Parent Album Name"]);
                        commands.Add("newAlbumTitle", values["Album Title"]);
                        commands.Add("newAlbumDesc", values["Album Description"]);
                        break;
                    }

                case Commands.MoveAlbum:
                    {
                        commands.Add("cmd", "move-album");
                        commands.Add("set_albumName", values["Source Album"]);
                        commands.Add("set_destalbumName", values["Destination Album"]);
                        break;
                    }

                case Commands.IncrementViewCount:
                    {
                        commands.Add("cmd", "increment-view-count");
                        commands.Add("itemId", values["Item Id"]);
                        break;
                    }

                case Commands.ImageProperties:
                    {
                        commands.Add("cmd", "image-properties");
                        commands.Add("id", values["Item Id"]);
                        break;
                    }

                case Commands.AddItemUrl:
                    {
                        commands.Add("cmd", "add-item");
                        commands.Add("set_albumName", values["Album Name"]);
                        commands.Add("userfile", values["User file"]);
                        commands.Add("caption", values["Caption"]);
                        commands.Add("force_filename", values["Force Filename"]);
                        commands.Add("auto_rotate", values["Auto Rotate"]);
                        foreach (KeyValuePair<string, string> value in values.Where(v => v.Key.StartsWith("extrafield.", StringComparison.CurrentCultureIgnoreCase)))
                        {
                            commands.Add(value.Key, value.Value);
                        }
                        break;
                    }
                case Commands.AddItemUpload:
                    {
                        commands.Add("cmd", "add-item");
                        commands.Add("set_albumName", values["Album Name"]);
                        commands.Add("userfile", values["User file"]); //HACK
                        commands.Add("caption", values["Caption"]);
                        commands.Add("force_filename", values["Force Filename"]);
                        commands.Add("auto_rotate", values["Auto Rotate"]);
                        foreach (KeyValuePair<string, string> value in values.Where(v => v.Key.StartsWith("extrafield.", StringComparison.CurrentCultureIgnoreCase)))
                        {
                            commands.Add(value.Key, value.Value);
                        }
                        break;
                    }
            }

            url += commands.ToPostString();

            HttpWebRequest gallery2Request = (HttpWebRequest)WebRequest.Create(url);
            gallery2Request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
            gallery2Request.Method = "POST";
            gallery2Request.ContentType = "application/x-www-form-urlencoded";
            gallery2Request.CookieContainer = _cookies;

            string valuesToPost = string.Empty;
            gallery2Request.ContentLength = valuesToPost.Length;

            using (StreamWriter streamWriter = new StreamWriter(gallery2Request.GetRequestStream(), System.Text.Encoding.ASCII))
            {
                streamWriter.Write(valuesToPost);
            }

            Collection<string> result = new Collection<string>();

            HttpWebResponse gallery2Response = (HttpWebResponse)gallery2Request.GetResponse();
            using (StreamReader reader = new StreamReader(gallery2Response.GetResponseStream()))
            {
                while (!reader.EndOfStream)
                {
                    result.Add(reader.ReadLine());
                }
            }

            return result;
        }
    }
}